#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QRandomGenerator>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QWidget>
#include <QLabel>
#include <QPushButton>
#include <QApplication>
#include <QFile>
#include <QTextStream>
#include <QFileDialog> // 添加 QFileDialog 头文件
#include <QMessageBox> // 添加 QMessageBox 头文件
#include "savedatathread.h"
#include "sensordatathread.h"
#include "qtboxstylepushbutton2.h"
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
    , plotX(new QCustomPlot(this))
    , plotY(new QCustomPlot(this))
    , plotZ(new QCustomPlot(this))
    , startTime(QDateTime::currentDateTime())
    , m_sensorThread(new SensorDataThread(this))
{
    ui->setupUi(this);
    // 设置窗口标题
    setWindowTitle("主从控制系统实时力值与坐标显示");
    // 创建中心部件
    QWidget *centralWidget = new QWidget(this);
    //centralWidget->setStyleSheet("background-color: #e6f2ff;");
    setCentralWidget(centralWidget);
    // 在MainWindow构造函数中添加以下代码
    setStyleSheet("background-color: #e6f2ff;"); // 淡蓝色背景

    // 创建垂直布局用于整体布局
    QVBoxLayout *mainLayout = new QVBoxLayout(centralWidget);

    // 创建水平布局用于放置三个图像
    QHBoxLayout *topLayout = new QHBoxLayout();

    // 设置每个绘图的大小策略，使其尽可能保持正方形
    plotX->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
    plotX->setMinimumSize(200, 200);
    plotY->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
    plotY->setMinimumSize(200, 200);
    plotZ->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
    plotZ->setMinimumSize(200, 200);

    topLayout->addWidget(plotX);
    topLayout->addWidget(plotY);
    topLayout->addWidget(plotZ);

    // 创建一个 QWidget 作为上半部分布局的容器
    QWidget *topWidget = new QWidget(this);
    topWidget->setLayout(topLayout);

    // 限制上半部分的最大高度，这里设置为 600 像素，可根据需求调整
    topWidget->setMaximumHeight(600);

    // 将上半部分的容器添加到主垂直布局
    mainLayout->addWidget(topWidget);

    // 创建一个新的垂直布局用于放置下半部分的控件
    QVBoxLayout *bottomMainLayout = new QVBoxLayout();

    // 创建水平布局用于放置力值标签
    QHBoxLayout *forceLayout = new QHBoxLayout();

    // 创建三个 QLabel 显示力的值
    labelX = new QLabel("X方向力:0", this);
    labelY = new QLabel("Y方向力:0", this);
    labelZ = new QLabel("Z方向力:0", this);

    forceLayout->addWidget(labelX);
    forceLayout->addWidget(labelY);
    forceLayout->addWidget(labelZ);

    // 创建水平布局用于放置坐标值标签
    QHBoxLayout *coordLayout = new QHBoxLayout();

    // 创建三个 QLabel 显示坐标值
    coordXLabel = new QLabel("X 坐标: 0", this);
    coordYLabel = new QLabel("Y 坐标: 0", this);
    coordZLabel = new QLabel("Z 坐标: 0", this);

    coordLayout->addWidget(coordXLabel);
    coordLayout->addWidget(coordYLabel);
    coordLayout->addWidget(coordZLabel);

    // 创建一个 QPushButton
    //QtBoxStylePushButton2 *button = new QtBoxStylePushButton2("quit", this);
    // 创建一个 QPushButton
    QtBoxStylePushButton2 *button2 = new QtBoxStylePushButton2(this);
    QtBoxStylePushButton2 *button = new QtBoxStylePushButton2(this);
    button2->setText("SAVE");
    //QPushButton *button2 = new QPushButton("save", this);

    button->setText("QUIT");
    // 将力值布局和坐标值布局添加到下半部分的垂直布局
    bottomMainLayout->addLayout(forceLayout);
    bottomMainLayout->addLayout(coordLayout);
    //bottomMainLayout->addWidget(button2);
    //bottomMainLayout->addWidget(button);
    // 创建一个QVBoxLayout用于放置按钮
    QVBoxLayout *buttonLayout = new QVBoxLayout();

    // 将按钮添加到新的垂直布局中
    buttonLayout->addWidget(button2);
    buttonLayout->addWidget(button);

    // 设置按钮布局的对齐方式为居中
    buttonLayout->setAlignment(Qt::AlignCenter);

    // 将按钮布局添加到底部主垂直布局中
    bottomMainLayout->addLayout(buttonLayout);
    // 创建一个 QWidget 作为下半部分布局的容器
    QWidget *bottomWidget = new QWidget(this);
    bottomWidget->setLayout(bottomMainLayout);

    // 将下半部分的容器添加到主垂直布局
    mainLayout->addWidget(bottomWidget);

    // 设置拉伸系数，让上半部分和下半部分按比例分配空间
    mainLayout->setStretch(0, 2); // 上半部分占 2 份
    mainLayout->setStretch(1, 1); // 下半部分占 1 份

    // 初始化每个绘图
    plotX->addGraph();
    plotX->xAxis->setLabel("时间(s)");
    plotX->yAxis->setLabel("x");

    plotY->addGraph();
    plotY->xAxis->setLabel("时间(s)");
    plotY->yAxis->setLabel("y");

    plotZ->addGraph();
    //plotZ->xAxis->setRange(0, 5);
    plotZ->xAxis->setLabel("时间(s)");
    plotZ->yAxis->setLabel("z");



    //connect(timer, &QTimer::timeout, this, &MainWindow::updatePlot);
    //timer->start(100);

    connect(button, &QPushButton::clicked, qApp, &QApplication::quit);
    connect(button2, &QPushButton::clicked, this, &MainWindow::saveSensorData);
    connect(m_sensorThread, &SensorDataThread::sensorDataUpdated, this, &MainWindow::updatePlot);

    // 启动传感器数据线程
    m_sensorThread->start();
}

MainWindow::~MainWindow()
{
    delete plotX;
    delete plotY;
    delete plotZ;

    delete labelX;
    delete labelY;
    delete labelZ;
    delete coordXLabel;
    delete coordYLabel;
    delete coordZLabel;
    m_sensorThread->stop();
    delete ui;
}

void MainWindow::updatePlot(double time, double valueX, double valueY, double valueZ)
{


    times.append(time);
    valuesX.append(valueX);
    valuesY.append(valueY);
    valuesZ.append(valueZ);
    allTimes.append(time);
    allValuesX.append(valueX);
    allValuesY.append(valueY);
    allValuesZ.append(valueZ);



    // 移除超出显示范围的数据
    while (!times.isEmpty() && time - times.first() > 5) {
        times.removeFirst();
        valuesX.removeFirst();
        valuesY.removeFirst();
        valuesZ.removeFirst();
    }
    // 更新每个绘图的数据 (在主线程中执行)
    plotX->graph(0)->setData(times, valuesX);
    plotX->xAxis->setRange(time - 5, time);
    plotX->yAxis->rescale();
    plotX->replot();

    plotY->graph(0)->setData(times, valuesY);
    plotY->xAxis->setRange(time - 5, time);
    plotY->yAxis->rescale();
    plotY->replot();

    plotZ->graph(0)->setData(times, valuesZ);
    plotZ->xAxis->setRange(time - 5, time);
    plotZ->yAxis->rescale();
    plotZ->replot();
    // 更新三个 QLabel 的文本内容显示力的值
    labelX->setText(QString("X force:%1").arg(valueX));
    labelY->setText(QString("Y force:%1").arg(valueY));
    labelZ->setText(QString("Z force:%1").arg(valueZ));

    // 更新三个 QLabel 的文本内容显示坐标值
    coordXLabel->setText(QString("X 坐标: %1").arg(valueX));
    coordYLabel->setText(QString("Y 坐标: %1").arg(valueY));
    coordZLabel->setText(QString("Z 坐标: %1").arg(valueZ));
}

void MainWindow::saveSensorData()
{
    QVector<QVector<double>> allData;
    allData.append(allTimes);
    allData.append(allValuesX);
    allData.append(allValuesY);
    allData.append(allValuesZ);

    QStringList headers = {"Time", "ValueX", "ValueY", "ValueZ"};

    // 使用文件对话框让用户选择保存位置
    QString fileName = QFileDialog::getSaveFileName(
        this,
        "save",
        QDir::homePath(),
        "CSV file (*.csv);;All Files (*)"
        );


    if (!fileName.isEmpty()) {
        // 创建数据保存线程，将数据、表头和文件名传递给线程
        SaveDataThread *thread = new SaveDataThread(allData, headers, fileName);

        // 连接保存成功信号：当数据成功保存后，在线程完成时显示成功消息
        // 使用 [=] 值捕获确保lambda可以访问外部变量（如thread指针）
        // 使用 deleteLater() 确保线程对象在线程完成后被安全销毁
        connect(thread, &SaveDataThread::saveSuccess, this, [=]() {
            QMessageBox::information(this, "success", "saved");
            thread->deleteLater(); // 线程任务完成后自动释放资源
        });

        // 连接保存失败信号：当数据保存失败时，显示错误消息并销毁线程
        // 错误消息通过信号参数传递，提供具体失败原因
        connect(thread, &SaveDataThread::saveFailed, this, [=](const QString &errorMsg) {
            QMessageBox::warning(this, "fail", errorMsg);
            thread->deleteLater(); // 无论成功或失败都需要释放线程资源
        });

        // 启动线程：开始在后台执行数据保存操作
        // 此时主线程继续执行，不会被文件IO操作阻塞
        thread->start();
    }
}

